上幾篇文章內,我們開發了一個讓用戶可以看到名言的功能。
不過,隨著資料量的增長,總不可能將所有要呈現給用戶的資料都寫在程式碼內。
這時候!就是使用資料庫的時候了!
我們之前的 inspire
是直接從程式碼內的某個陣列取出名言。現在我們小小修改一下這個需求,讓他可以從資料庫裡面取出。
我們來設計一個簡單的資料表 quotes
,來儲存我們的名言:
資料表欄位名稱 | 資料欄位內容 |
---|---|
id | 資料 id |
content | 名言內容 |
created_at | 資料建立時間 |
updated_at | 資料編輯時間 |
下面我們來聊聊怎麼實作這個資料庫
在之前我們所使用的 laradock,已經順便幫我們把資料庫建立起來了。不過麻煩的是,因為他所使用的版本太新(latest),所以部分 MySQL 連線工具,如筆者所使用的 Sequel Pro 並不支援。
不過幸運的是,用 laradock 改變資料庫版本是相對容易的事情!我們就來嘗試看看吧!
首先,我們進入 laradock 裡面,找到 .env
檔案。接著在裡面找
MYSQL_VERSION=latest
在這裡把 latest
改成 5.7
接著,因為舊的資料可能會導致錯誤,所以我們要將 laradock 資料庫相關的舊資料清除。
進到 ~/.laradock
這個隱藏資料夾,你會發現裡面有一個 data
資料夾,我們把整個資料夾清空。
最後,我們回到專案的 laradock 資料夾,重新建立 mysql 的服務:
$ docker-compose up -d --build mysql
順利的話,你應該可以看到 Successfully built
之類的字樣。
然後,我們嘗試連線資料庫看看。細心的讀者可能在修改 .env
檔案時就發現了,預設帳號密碼其實寫在裡面:
MYSQL_DATABASE=default
MYSQL_USER=default
MYSQL_PASSWORD=secret
我們用這組帳號密碼,測試連線 127.0.0.1
的 mysql 看看
如果能正確連線,看到 default
這個資料庫,就代表我們成功建立起資料庫環境囉!
接著,我們要來介紹一個網頁框架常見的功能:資料庫遷移(migration)
什麼是資料庫遷移呢?簡單來說,資料庫遷移很像是針對資料庫格式的版本控制。
過去在開發時,一個很頭痛的事情,就是如何同步各個地方資料庫的格式。如果有新進員工準備要開發,可能要某個工程師匯出自己正在開發的資料庫,或者更糟,直接匯出至正式站的資料庫,讓新的工程師匯入進自己的環境來進行開發。
為了解決這個問題,有的網頁框架引入了一個新的功能:資料庫遷移。利用程式碼來修改資料庫格式,所以資料庫格式和其他程式碼都在版本控制內。如此一來,每次有新的工程師需要建構開發環境時,你就只需要在他取得程式碼的同時,提醒他記得跑一下 migration 就可以了。
解釋起來有點繁瑣,不如我們實作看看吧!
首先,我們修改專案內的 .env
,讓專案可以透過前面所說的帳密與資料庫連線:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secret
接著,我們在專案內跑
$ php artisan migrate
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.07 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.08 seconds)
如果看到這兩個 migration 成功運行,恭喜你,那就代表我們的遷移運作成功囉!我們進資料庫看看:
可以看到,Laravel 的 migration 建立了三張資料表:一張用來儲存 migration 的內容,另外兩張則是 Laravel 預設的資料表。
安裝成功之後,我們來看看如何建立自己的 migration,來改變現有的資料庫格式。
我們先用 artisan
來產生一個 migration create_quotes_table
$ php artisan make:migration create_quotes_table
Created Migration: 2019_09_10_183501_create_quotes_table
這樣就建立好了,我們來看看裡面寫了些什麼。打開 database/migrations/2019_09_10_183501_create_quotes_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateQuotesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('quotes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('quotes');
}
}
Laravel 很聰明的根據我們命名的 migration 名稱 create_quotes_table
猜到我們可能是要建立 quotes
這個資料表,所以幫我們填寫了部分的內容。
Schema::create('quotes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
});
這幾行程式的作用是什麼呢?我們直接來測試看看!
我們重新跑一次 php artisan migrate
$ php artisan migrate
Migrating: 2019_09_10_183501_create_quotes_table
Migrated: 2019_09_10_183501_create_quotes_table (0.06 seconds)
然後,我們到資料庫,看看這段程式實際上產生了什麼影響
成功建立起 quotes
資料表了! 我們看看內容
前面我們所列舉的四個欄位內,有三個都已經預設建立了,真不錯!
我們現在只需要多新增一個欄位 content
就好,首先,我們在資料庫裡面還原我們所做的事情
$ php artisan migrate:rollback --step=1
Rolling back: 2019_09_10_183501_create_quotes_table
Rolled back: 2019_09_10_183501_create_quotes_table (0.03 seconds)
這個指令可以回溯遷移的上一步,根據--step=
裡面的數字改變,回溯多少步驟都可以。
另外補充說明一下 rollback 的機制。在使用 migrate
的時候,會呼叫 up
函式。而使用 migrate:rollback
的時候,我們會呼叫 migration 裡面 down()
這個函式的內容來復原這個 migration 所做的事情。
所以,在每個 migration 裡面,down()
都應該要實作能復原up()
所做的事。
在這裏,我們的 up()
所做的事情是建立 quotes
資料表,所以 down()
所做的事情就是刪除 quotes
資料表,也就是Laravel 所產生的內容:
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('quotes');
}
回溯的機制解釋完,還是得看看實際的作用,我們用指定看看是否成功回溯
$ php artisan migrate:status
+------+------------------------------------------------+-------+
| Ran? | Migration | Batch |
+------+------------------------------------------------+-------+
| Yes | 2014_10_12_000000_create_users_table | 1 |
| Yes | 2014_10_12_100000_create_password_resets_table | 1 |
| No | 2019_09_10_183501_create_quotes_table | |
+------+------------------------------------------------+-------+
成功了!我們確實讓 2019_09_10_183501_create_quotes_table
沒有運作到。
然後我們改寫 2019_09_10_183501_create_quotes_table.php
加入 content
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateQuotesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('quotes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('content', 255);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('quotes');
}
}
看出來了嗎?其實我們只加入了一行而已
我們重新跑一次 migrate
php artisan migrate
Migrating: 2019_09_10_183501_create_quotes_table
Migrated: 2019_09_10_183501_create_quotes_table (0.04 seconds)
然後看看資料庫
成功囉!我們建立起需求中的 quotes
資料庫了!
最後總結一下今天我們學到了什麼
今天我們學會 migration 是什麼,怎麼新增 migration,跟怎麼根據需求將 migration 修改成我們要的樣子
希望今天大家有所收穫,我們明天見!
補充一下,.env 中
MYSQL_USER=
MYSQL_PASSWORD=
不可以有 #
我因密碼中有個 #
以致無法運作。
HI 大大你好
在跟著你的步驟時有遇到一些問題
執行 php artisan migrate
時,會出現以下錯誤
已查看phpinfo()
,確認支援mysql
參考做法,執行指令 composer require doctrine/dbal
但錯誤依舊
再麻煩大大解惑了QQ 謝謝!!
阿阿 沒問題了
我發現php.ini的設定檔,extension的設定
不過我還是想問 這個設定沒有把註解取消時,為何phpinfo()上面會寫enable QQ?